﻿using System.Collections.Generic;
using System.Security.Principal;
using System.Text;
using NUnit.Framework;

namespace System.Data.MdxClient.Tests
{
    [TestFixture()]
    public class MdxConnectionStringBuilderTests
    {
        [Test()]
        public void CanCreateConnectionString()
        {
            var builder = new MdxConnectionStringBuilder();
            builder.Catalog = "myDataBase";
            builder.DataSource = "myServerAddress";
            builder.IntegratedSecurity = IntegratedSecurity.Sspi;

            var connectionString = builder.ConnectionString;
            Assert.That(connectionString, Is.EqualTo("Data Source=myServerAddress;Catalog=myDataBase;Integrated Security=Sspi"));
        }

        [Test()]
        public void ToStringShouldReturnConnectionString()
        {
            var builder = new MdxConnectionStringBuilder();
            builder.Catalog = "myDataBase";
            builder.DataSource = "myServerAddress";
            Assert.AreEqual(builder.ConnectionString, builder.ToString());
        }

        [Test()]
        public void CanSetParseApplicationName()
        {
            const String AppName = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.ApplicationName = AppName;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("SSPropInitAppName=" + AppName));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ApplicationName, Is.EqualTo(AppName));
        }

        [Test()]
        public void CanSetParseAutoSyncPeriod()
        {
            const Int32 AutoSyncPeriod = 1;

            var builder = new MdxConnectionStringBuilder();
            builder.AutoSyncPeriod = AutoSyncPeriod;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("AutoSyncPeriod=" + AutoSyncPeriod));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.AutoSyncPeriod, Is.EqualTo(AutoSyncPeriod));
        }

        [Test()]
        public void BrowsableConnectionStringShouldHaveExpectedDefault()
        {
            var builder = new MdxConnectionStringBuilder();
            builder.BrowsableConnectionString = true;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.Empty);

            builder = new MdxConnectionStringBuilder();
            Assert.That(builder.BrowsableConnectionString, Is.True);
        }

        [Test()]
        public void CanSetParseCharacterEncoding()
        {
            var builder = new MdxConnectionStringBuilder();
            builder.CharacterEncoding = Encoding.UTF32;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Character Encoding=UTF-32"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.CharacterEncoding, Is.Not.Null);
            Assert.That(builder.CharacterEncoding, Is.TypeOf<UTF32Encoding>());
        }

        [Test()]
        public void CanSetParseClientProcessId()
        {
            const String ClientProcessId = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.ClientProcessId = ClientProcessId;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("ClientProcessID=" + ClientProcessId));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ClientProcessId, Is.EqualTo(ClientProcessId));
        }

        [Test()]
        public void CanSetParseCommandTimeout()
        {
            const Int32 CommandTimeout = 50;

            var builder = new MdxConnectionStringBuilder();
            builder.CommandTimeout = CommandTimeout;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Timeout=" + CommandTimeout));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.CommandTimeout, Is.EqualTo(CommandTimeout));
        }

        [Test()]
        public void CanSetParseCompressionLevel()
        {
            const Int32 CompressionLevel = 9;

            var builder = new MdxConnectionStringBuilder();
            builder.CompressionLevel = CompressionLevel;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Compression Level=" + CompressionLevel));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.CompressionLevel, Is.EqualTo(CompressionLevel));
        }

        [Test()]
        public void CanSetParseConnectTimeout()
        {
            const Int32 ConnectTimeout = 50;

            var builder = new MdxConnectionStringBuilder();
            builder.ConnectTimeout = ConnectTimeout;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Connect Timeout=" + ConnectTimeout));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ConnectTimeout, Is.EqualTo(ConnectTimeout));
        }

        [Test()]
        public void CanSetParseConnectTo()
        {
            const String ConnectTo = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.ConnectTo = ConnectTo;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("ConnectTo=" + ConnectTo));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ConnectTo, Is.EqualTo(ConnectTo));
        }

        [Test()]
        public void CanSetParseDataSource()
        {
            const String DataSource = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.DataSource = DataSource;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Data Source=" + DataSource));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.DataSource, Is.EqualTo(DataSource));
        }

        [Test()]
        public void DataSourceAcceptsAliases()
        {
            var builder = new MdxConnectionStringBuilder("DataSourceLocation=foo");
            Assert.That(builder.DataSource, Is.EqualTo("foo"));
        }

        [Test()]
        public void CanSetParseDisablePrefetchFacts()
        {
            const Boolean DisablePrefetchFacts = true;

            var builder = new MdxConnectionStringBuilder();
            builder.DisablePrefetchFacts = DisablePrefetchFacts;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Disable Prefetch Facts=" + DisablePrefetchFacts));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.DisablePrefetchFacts, Is.EqualTo(DisablePrefetchFacts));
        }

        [Test()]
        public void CanSetParseEncryptionPassword()
        {
            const String EncryptionPassword = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.EncryptionPassword = EncryptionPassword;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Encryption Password=" + EncryptionPassword));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.EncryptionPassword, Is.EqualTo(EncryptionPassword));
        }

        [Test()]
        public void CanSetParseImpersonationLevel()
        {
            //TODO : have iterative unit test
            const TokenImpersonationLevel ImpersonationLevel = TokenImpersonationLevel.Delegation;

            var builder = new MdxConnectionStringBuilder();
            builder.ImpersonationLevel = ImpersonationLevel;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Impersonation Level=Delegate"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ImpersonationLevel, Is.EqualTo(ImpersonationLevel));
        }

        [Test()]
        public void ImpersonationLevelForNoneShouldUseAnonymousConnectionStringValue()
        {
            const TokenImpersonationLevel ImpersonationLevel = TokenImpersonationLevel.None;

            var builder = new MdxConnectionStringBuilder();
            builder.ImpersonationLevel = ImpersonationLevel;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Impersonation Level=" + TokenImpersonationLevel.Anonymous));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ImpersonationLevel, Is.EqualTo(TokenImpersonationLevel.Anonymous));
        }

        [Test()]
        public void CanSetParseCatalog()
        {
            const String InitialCatalog = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.Catalog = InitialCatalog;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Catalog=" + InitialCatalog));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.Catalog, Is.EqualTo(InitialCatalog));
        }

        [Test()]
        public void CatalogAcceptsAliases()
        {
            var builder = new MdxConnectionStringBuilder("Initial Catalog=foo");
            Assert.That(builder.Catalog, Is.EqualTo("foo"));

            builder = new MdxConnectionStringBuilder("Database=foo");
            Assert.That(builder.Catalog, Is.EqualTo("foo"));
        }

        [Test()]
        public void CanSetParseIntegratedSecurity()
        {
            const IntegratedSecurity IntegratedSecurity = IntegratedSecurity.Sspi;

            var builder = new MdxConnectionStringBuilder();
            builder.IntegratedSecurity = IntegratedSecurity;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Integrated Security=" + IntegratedSecurity));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.IntegratedSecurity, Is.EqualTo(IntegratedSecurity));
        }

        [Test()]
        public void CanSetParseLocaleIdentifier()
        {
            const Int16 LocaleIdentifier = 5;

            var builder = new MdxConnectionStringBuilder();
            builder.LocaleIdentifier = LocaleIdentifier;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("LocaleIdentifier=" + LocaleIdentifier));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.LocaleIdentifier, Is.EqualTo(LocaleIdentifier));
        }

        [Test()]
        public void CanSetParseLocation()
        {
            const String Location = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.Location = Location;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Location=" + Location));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.Location, Is.EqualTo(Location));
        }

        [Test()]
        public void CanSetParsePacketSize()
        {
            const Int32 PacketSize = 1000;

            var builder = new MdxConnectionStringBuilder();
            builder.PacketSize = PacketSize;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Packet Size=" + PacketSize));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.PacketSize, Is.EqualTo(PacketSize));
        }

        [Test()]
        public void CanSetParsePassword()
        {
            const String Password = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.Password = Password;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Password=" + Password));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.Password, Is.EqualTo(Password));
        }

        [Test()]
        public void PasswordAcceptsAliases()
        {
            var builder = new MdxConnectionStringBuilder("pwd=foo");
            Assert.That(builder.Password, Is.EqualTo("foo"));
        }

        [Test()]
        public void CanSetParsePersistSecurityInfo()
        {
            const Boolean PersistSecurityInfo = true;

            var builder = new MdxConnectionStringBuilder();
            builder.PersistSecurityInfo = PersistSecurityInfo;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Persist Security Info=" + PersistSecurityInfo));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.PersistSecurityInfo, Is.EqualTo(PersistSecurityInfo));
        }

        [Test()]
        public void CanSetParseProtectionLevel()
        {
            var tests = new Dictionary<ProtectionLevel, String>();
            tests.Add(ProtectionLevel.ConnectOnly, "ProtectionLevel=CONNECT");
            tests.Add(ProtectionLevel.Encryption, "ProtectionLevel=PKTPRIVACY");
            tests.Add(ProtectionLevel.None, String.Empty);
            tests.Add(ProtectionLevel.Signing, "ProtectionLevel=PKTINTEGRITY");

            foreach (var test in tests)
            {
                var builder = new MdxConnectionStringBuilder();
                builder.ProtectionLevel = test.Key;
                var connectionString = builder.ToString();
                Assert.That(connectionString, Is.EqualTo(test.Value));

                builder = new MdxConnectionStringBuilder(connectionString);
                Assert.That(builder.ProtectionLevel, Is.EqualTo(test.Key));
            }
        }

        [Test()]
        public void ProtectionLevelAcceptsAliases()
        {
            var builder = new MdxConnectionStringBuilder("ProtectionLevel=PKT INTEGRITY");
            Assert.That(builder.ProtectionLevel, Is.EqualTo(ProtectionLevel.Signing));

            builder = new MdxConnectionStringBuilder("ProtectionLevel=PKT PRIVACY");
            Assert.That(builder.ProtectionLevel, Is.EqualTo(ProtectionLevel.Encryption));
        }

        [Test()]
        public void CanSetParseProtocolFormat()
        {
            //TODO : have iterative unit test
            const ProtocolFormat ProtocolFormat = ProtocolFormat.Xml;

            var builder = new MdxConnectionStringBuilder();
            builder.ProtocolFormat = ProtocolFormat;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Protocol Format=XML"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.ProtocolFormat, Is.EqualTo(ProtocolFormat));
        }

        [Test()]
        public void CanSetParseSessionId()
        {
            const String SessionId = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.SessionId = SessionId;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("SessionID=" + SessionId));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.SessionId, Is.EqualTo(SessionId));
        }

        [Test()]
        public void CanSetParseSspi()
        {
            //TODO : have iterative unit test
            const SecurityPackage Sspi = SecurityPackage.Ntlm;

            var builder = new MdxConnectionStringBuilder();
            builder.Sspi = Sspi;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("SSPI=NTLM"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.Sspi, Is.EqualTo(Sspi));
        }

        [Test()]
        public void CanSetParseTransportCompression()
        {
            //TODO : have iterative unit test
            const TransportCompression TransportCompression = TransportCompression.Gzip;

            var builder = new MdxConnectionStringBuilder();
            builder.TransportCompression = TransportCompression;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Transport Compression=GZIP"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.TransportCompression, Is.EqualTo(TransportCompression));
        }

        [Test()]
        public void CanSetParseUseEncryptionForData()
        {
            const Boolean UseEncryptionForData = true;

            var builder = new MdxConnectionStringBuilder();
            builder.UseEncryptionForData = UseEncryptionForData;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("Use Encryption For Data=True"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.UseEncryptionForData, Is.EqualTo(UseEncryptionForData));
        }

        [Test()]
        public void CanSetParseUseExistingFile()
        {
            const Boolean UseExistingFile = true;

            var builder = new MdxConnectionStringBuilder();
            builder.UseExistingFile = UseExistingFile;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("UseExistingFile=True"));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.UseExistingFile, Is.EqualTo(UseExistingFile));
        }

        [Test()]
        public void CanSetParseUserName()
        {
            const String UserName = "foo";

            var builder = new MdxConnectionStringBuilder();
            builder.UserName = UserName;
            var connectionString = builder.ToString();
            Assert.That(connectionString, Is.EqualTo("UserName=" + UserName));

            builder = new MdxConnectionStringBuilder(connectionString);
            Assert.That(builder.UserName, Is.EqualTo(UserName));
        }

        [Test()]
        public void UserNameAcceptsAliases()
        {
            var builder = new MdxConnectionStringBuilder("Authenticated User=foo");
            Assert.That(builder.UserName, Is.EqualTo("foo"));

            builder = new MdxConnectionStringBuilder("UID=foo");
            Assert.That(builder.UserName, Is.EqualTo("foo"));

            builder = new MdxConnectionStringBuilder("User ID=foo");
            Assert.That(builder.UserName, Is.EqualTo("foo"));
        }
    }
}
